home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Power 1997 January
/
macpower199701.bin
/
AMUG
/
Publishing_19
/
Alpha 6.5.sit
/
Tcl
/
Modes
/
htmlEngine.tcl
< prev
next >
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
NeXTSTEP
RISC OS/Acorn
UTF-8
Wrap
Text File
|
1996-08-15
|
89.6 KB
|
3,122 lines
|
[
TEXT/ALFA
]
#===============================================================================
#
# htmlEngine.tcl (called from html.tcl)
#
# Part of HTML mode 1.2
#
# General Support Routines
#
# Author: Johan Linde <jl@theophys.kth.se>
#
# If you make improvements to this file, please share them!
#
#===============================================================================
# The first two are taken from latexEngine.tcl
proc htmlIsUnsignedInteger {str1} {
return [regexp {^[0-9]+$} [string trim $str1]]
}
proc htmlIsPositiveInteger {str1} {
if { [htmlIsUnsignedInteger $str1] } then {
if { ![regexp {^0+$} [string trim $str1]] } {
return 1
}
}
return 0
}
proc htmlIsInteger {str} {
return [regexp {^-?[0-9]+$} [string trim $str]]
}
# Checks to see if the current window is empty, except for whitespace.
proc htmlIsEmptyFile {} {
return [htmlIsWhite [getText 0 [maxPos]]]
}
proc htmlNotYet {} {
alertnote "Not yet, but coming soon."
}
proc htmlSetCase {elem} {
global HTMLmodeVars
set useLowerCase $HTMLmodeVars(useLowerCase)
if {$useLowerCase} {
return [string tolower $elem]
} else {
return [string toupper $elem]
}
}
proc htmlIsThereHomePage {} {
global homePagePath
if {![info exists homePagePath] || ![string length $homePagePath] || ¥
![file exists $homePagePath]} {
alertnote "You must set your Home page folder."
if {[catch {pathProc d "Home Page folder"}] || ![info exists homePagePath] || ¥
![string length $homePagePath] || ![file exists $homePagePath]} {
error
}
}
}
proc htmlIsThereBaseURL {msg} {
global HTMLmodeVars
if {![string length $HTMLmodeVars(baseURL)]} {
alertnote $msg
htmlServerURL
if {![string length $HTMLmodeVars(baseURL)]} {
error
}
}
}
#
# Mark file
#
proc HTMLMarkFile {} {
set end [maxPos]
set pos 0
set l {}
set exp {<[Hh][1-6].*>[^<]*</[Hh][1-6]>}
while {![catch {search -s -f 1 -r 1 -m 0 -i 0 $exp $pos} res]} {
set start [lindex $res 0]
set end [lindex $res 1]
set text [getText $start $end]
# Remove tabs and returns from text.
regsub -all "¥[¥t¥r¥]+" $text " " text
set headtext ""
# remove all tags from text
while {1} {
set lt [string first < $text ]
if {$lt < 0} { break }
if {$lt > 0} { append headtext [string range $text 0 [expr $lt - 1]] }
set text [string range $text $lt end]
set gt [string first > $text]
if {$gt < 0} { break }
set text [string range $text [expr $gt + 1] end]
}
# Set mark only on one line.
if {$end > [nextLineStart $start]} {
set end [expr [nextLineStart $start] - 1]
}
set indlevel [getText [expr $start + 2] [expr $start + 3]]
if {$indlevel > 0 && $indlevel < 7} {
set lab [string range " " 2 $indlevel]
append lab $lab $indlevel " " $headtext
# remove ;^</!( from label
# regsub -all {[;^</!(]} $lab {} lab
# Cut the menu item if it's longer than 30 letters, not to make it too long.
if {[string length $lab] > 30} {
set lab "[string range $lab 0 29]ノ"
}
setNamedMark $lab $start $start $end
}
set pos $end
}
message "Marks set."
}
# Opens a file in the home page folder, if clicked on a link to a text file.
# If the file doesn't exist, it can be opened in a new empty window, and automatically
# saved in the right place.
proc HTMLDblClick {from to} {
global htmlURLAttr homePagePath filepats
# Build regular expressions with URL attrs.
set exp "("
foreach attr $htmlURLAttr {
append exp "$attr|"
}
set exp [string trimright $exp |]
append exp ")¥"?(¥[^ ¥¥t¥">¥]+)¥"?"
# Check if user clicked on a link.
if {![catch {search -s -f 0 -r 1 -i 1 -m 0 $exp $from} res] && [lindex $res 1] > $from} {
# Get path to this window.
set extra [htmlThisFilePath 1]
if {[string length $extra]} {
set extraPath [lindex $extra 0]
set thisURL [string range [file dirname [lindex $extra 1]] ¥
[expr [string length $homePagePath] + 1] end]
} else {
return
}
regexp -nocase $exp [getText [lindex $res 0] [lindex $res 1]] dum1 dum2 linkTo
# Check if link begins with string from BASE to home page.
if {[string match "$extraPath*" $linkTo]} {
# Remove extraPath.
set linkTo [string range $linkTo [string length $extraPath] end]
set linkToPath [htmlPathToFile $thisURL $linkTo]
} else {
set linkToPath ""
}
# Does the file exist? Ignore it if it's outside home page folder.
# Then it point to someone else's home page.
if {[string match "$homePagePath*" $linkToPath]} {
if {[file exists $linkToPath] && ![file isdirectory $linkToPath]} {
# Is it a text file?
getFileInfo $linkToPath filetest
if {$filetest(type) != "TEXT"} {
message "[file tail $linkToPath] is not a text file."
} else {
edit -c $linkToPath
}
} else {
set isAnHtmlFile 0
foreach suffix $filepats(HTML) {
if {[string match $suffix $linkToPath]} {set isAnHtmlFile 1}
}
if {(![file exists $linkToPath] && !$isAnHtmlFile) || [file isdirectory $linkToPath]} {
message "Cannot open [file tail $linkToPath]."
} else {
set htmlFile [file tail $linkToPath]
if {[lindex [dialog -w 350 -h 140 -t "The file '$htmlFile' does not exist.¥
Do you want to open a new empty window with this name?¥
It will automatically be saved in the right place,¥
and if necessary, new folders will be created." 10 10 340 100 ¥
-b Yes 20 110 85 130 -b No 115 110 180 130] 1]} {return}
# Create a new file and open it.
set path [split [string range [file dirname $linkToPath] ¥
[expr [string length $homePagePath] + 1] end] :]
set linkToPath $homePagePath
foreach p $path {
append linkToPath ":$p"
# make new folders if needed.
if {![file exists $linkToPath]} {
mkdir $linkToPath
} elseif {[file exists $linkToPath] && ![file isdirectory $linkToPath]} {
alertnote "Cannot make a new folder '[file tail $linkToPath]'.¥
There is already a file with the same name."
return
}
}
append linkToPath ":$htmlFile"
# create an empty file.
set fid [open $linkToPath w]
# I suppose it's best to close it, too.
close $fid
edit $linkToPath
}
}
} else {
message "This link points outside your home page."
}
} else {
message "You must click on a URL."
}
}
# Snatch the current selection into htmlCurSel, set flag whether there is one
proc htmlGetSel {{sel ""}} {
global htmlCurSel htmlIsSel
set htmlCurSel [string trim $sel]
if {![string length $htmlCurSel]} {
set htmlCurSel [string trim [getSelect]]
}
set htmlIsSel [string length $htmlCurSel]
}
#
# return positions of tags of including elements, as a list of 5 elements --
# openstart openend closestart closeend elementname.
# Elements without a closing tag are ignored.
# args: point to start search backward from; point which must be enclosed
#
# if any problem, return just {0}
#
proc htmlGetContainer {curPos inclPos} {
set startPos $curPos
set startPos2 $inclPos
set searchFinished 0
message "Searching for enclosing tagsノ"
while {!$searchFinished} {
# find first tag
set isStartTag 0
while {!$isStartTag} {
if {[catch {search -s -f 0 -r 1 -i 0 -m 0 {<[^<>]+>} $startPos} res] ||
[lindex $res 0] > [maxPos]} {
message ""
return {0}
}
set tag1start [lindex $res 0]
set tag1end [lindex $res 1]
# get element name
if {![regexp {<([^ ¥t¥r]+).*>} [getText $tag1start $tag1end] tmp tag]} {
message ""
return {0}
}
# is this a closing tag?
if {[string range $tag 0 0] != "/"} { set isStartTag 1}
set startPos [expr $tag1start - 1]
}
set elem [string toupper $tag]
# find closing tag
set x </${tag}>
set sPos $tag1end
set sPos2 $tag1end
while {1} {
set res [search -s -f 1 -r 1 -i 1 -m 0 -n $x $sPos]
# Found any closing tag.
if {![llength $res]} {break}
# Look for another opening tag of the same element.
set y "<${tag}(¥[ ¥¥t¥¥r¥]+|>)"
set res2 [search -s -f 1 -r 1 -i 1 -m 0 -n $y $sPos2]
# Is it further away than the closing tag.
if {![llength $res2] || [lindex $res2 0] > [lindex $res 0]} {break}
# If not, find the next closing tag.
set sPos [lindex $res 1]
set sPos2 [lindex $res2 1]
}
set tag2start [lindex $res 0]
set tag2end [lindex $res 1]
# If container enclosed along with us, or there is no closing tag,
# continue searching.
if {![llength $res] || $tag2end < $inclPos} {
set startPos [expr $tag1start - 1]
} else {
set Container "$tag1start $tag1end $tag2start $tag2end"
set searchFinished 1
set element $elem
}
}
goto $curPos
message ""
return [concat $Container $element]
}
#
# return position an opening tag if the first element to the left
# of startPos is an element with only an opening tag, as a list of 3 elements --
# openstart openend elementname.
#
# if any problem, return empty string
#
proc htmlGetOpening {startPos} {
if {[catch {search -s -f 0 -r 1 -i 0 -m 0 {<[^<>]+>} $startPos} res] ||
[lindex $res 0] > [maxPos]} {
return
}
set tag1start [lindex $res 0]
set tag1end [lindex $res 1]
# get element name
if {![regexp {<([^ ¥t¥r]+).*>} [getText $tag1start $tag1end] tmp tag]} {
return
}
# is this a closing tag?
if {[string range $tag 0 0] == "/"} {return}
# find closing tag
set x </${tag}>
set sPos $tag1end
set sPos2 $tag1end
while {1} {
set res [search -s -f 1 -r 1 -i 1 -m 0 -n $x $sPos]
# Found any closing tag.
if {![llength $res]} {break}
# Look for another opening tag of the same element.
set y "<${tag}(¥[ ¥¥t¥¥r¥]+|>)"
set res2 [search -s -f 1 -r 1 -i 1 -m 0 -n $y $sPos2]
# Is it further away than the closing tag.
if {![llength $res2] || [lindex $res2 0] > [lindex $res 0]} {break}
# If not, find the next closing tag.
set sPos [lindex $res 1]
set sPos2 [lindex $res2 1]
}
if {![llength $res] } {
return "$tag1start $tag1end [string toupper $tag]"
} else {
return
}
}
# Asks for a file and returns the file name including the relative path from
# current window, provided both are in the home page folder. Otherwise an empty
# string is returned.
proc htmlGetFile {} {
global HTMLmodeVars homePagePath
# get path to this window.
set this [htmlThisFilePath 0]
if {[string length $this]} {
set extraPath [lindex $this 0]
set thisFile [lindex $this 1]
} else {
return
}
# Get the file to link to.
if {[catch {getfile "Select file to link to."} linkFile]} {
return
}
# Is this file in home page folder?
if {![string match ${homePagePath}* $linkFile]} {
alertnote "'[file tail $linkFile]' is not in the home page folder. In this way you can only¥
make links to files in the home page folder."
return
}
set linkTo "$extraPath[htmlRelativePath $thisFile $linkFile]"
# Add URL to cache.
htmlAddToCache URLs $linkTo
return $linkTo
}
# Returns the path to the current window, with corrections if BASE is used.
# Returns path from BASE to home page.
# If the current window is not in the home page folder an empty sring is returned.
# Called with 0 if called from htmlGetFile.
# Called with 1 if called from HTMLDblClick. (0 or 1 determines the error message.)
proc htmlThisFilePath {errorMsg} {
global homePagePath
# Check that homePagePath is set.
if {[catch htmlIsThereHomePage]} {return}
# Remove ending :, otherwise glob will get confused, as well as other parts of the code.
set homePagePath [string trimright $homePagePath :]
set thisFile [lindex [winNames -f] 0]
# Strip off trailing garbage (if any)
regexp {(.*) <[0-9]+>} $thisFile dummy thisFile
set extraPath ""
# Look for BASE element.
if {![catch {search -s -f 1 -r 1 -i 1 -m 0 {<BASE[^>]*>} 0} res] && ¥
[regexp {[hH][rR][eE][fF]=¥"?([^ ¥t¥r¥">]+)} [getText [lindex $res 0] ¥
[lindex $res 1]] dum href]} {
set extra [htmlPathFromBASE $href]
if {![string length $extra]} {return}
set extraPath [lindex $extra 0]
set thisFile [lindex $extra 1]
} else {
# Check if window is saved.
if {![file exists $thisFile]} {
if {$errorMsg} {
set etxt "You must save the window, otherwise it cannot be determined¥
where the link is pointing."
} else {
set etxt "You must save the window. If you save, you will then be prompted¥
for a file to link to."
}
if {[lindex [dialog -w 400 -h 100 -t $etxt 10 10 390 60 ¥
-b Save 20 70 85 90 ¥
-b Cancel 110 70 175 90] 1]} {
return
}
if {![catch {saveAs [lindex [winNames] 0]}]} {
set thisFile [lindex [winNames -f] 0]
regexp {(.*) <[0-9]+>} $thisFile dummy thisFile
} else {
return
}
}
# Is window in home page folder?
if {![string match ${homePagePath}* $thisFile]} {
if {$errorMsg} {
message "Window not in home page folder. Cannot determine where the link is pointing."
} else {
alertnote "Current window is not in the home page folder. In this way you can only¥
make links between files in the home page folder."
}
return
}
}
return [list $extraPath $thisFile]
}
proc htmlPathFromBASE {href} {
global HTMLmodeVars homePagePath
# When BASE is used, Server URL must be set.
if {[catch {htmlIsThereBaseURL "You must set the Server URL when you use the BASE element."}]} {
return
}
set baseURL $HTMLmodeVars(baseURL)
set basePath $HTMLmodeVars(basePath)
set extraPath ""
set thisFile $homePagePath
# If BASE is somewhere else, make an absolute link.
if {![string match "${baseURL}*" $href]} {
set extraPath "$baseURL$basePath"
append thisFile ":dummy"
} elseif {[string match "$baseURL$basePath*" $href]} {
# BASE point to Home page.
set bPath [split [string range $href [string length "$baseURL$basePath"] end] /]
foreach b $bPath {
append thisFile ":" $b
}
# If bPath is empty we must add a dummy file.
if {$thisFile == $homePagePath} {append thisFile ":dummy"}
} else {
# Find path from BASE to Home page.
set thisBase [split [string range $href [string length $baseURL] end] /]
set thisBase [lrange $thisBase 0 [expr [llength $thisBase] - 2]]
set bPath [split [string trimright $basePath /] /]
set i 0
while {[llength $thisBase] > $i && [llength $bPath] > $i ¥
&& [lindex $thisBase $i] == [lindex $bPath $i]} {
incr i
}
set thisBase [lrange $thisBase $i end]
set bPath [lrange $bPath $i end]
foreach t $thisBase {
append extraPath "../"
}
foreach b $bPath {
append extraPath "$b/"
}
append thisFile ":dummy"
}
return [list $extraPath $thisFile]
}
# Returns toFile including relative path from fromFile.
proc htmlRelativePath {fromFile toFile} {
set fromdir [split [file dirname $fromFile] :]
set todir [split [file dirname $toFile] :]
# Remove the common path.
set i 0
while {[llength $fromdir] > $i && [llength $todir] > $i ¥
&& [lindex $fromdir $i] == [lindex $todir $i]} {
incr i
}
set fromdir [lrange $fromdir $i end]
set todir [lrange $todir $i end]
# Insert ../
foreach f $fromdir {
append linkTo "../"
}
# Add the path.
foreach f $todir {
append linkTo "$f/"
}
# Add file name
append linkTo [file tail $toFile]
return $linkTo
}
# Check that links are valid.
proc htmlCheckLinks {where} {
global homePagePath HTMLmodeVars
# Check that homePagePath is set.
if {[catch htmlIsThereHomePage]} {return}
# Remove ending :, otherwise it will all be a mess.
set homePagePath [string trimright $homePagePath :]
# Check that the server URL is set.
if {[catch {htmlIsThereBaseURL "You must set the Server URL."}]} {return}
# Save all open window?
set savewin [askyesno -c "Save all open windows before checking links?"]
if {$savewin == "cancel"} {
return
} elseif {$savewin == "yes"} {saveAll}
if {$where == "file"} {
if {[catch {getfile "Select file to scan."} files]} {return}
# Is this a text file?
getFileInfo $files filetest
if {$filetest(type) != "TEXT"} {
alertnote "'[file tail $files]' is not a text file."
return
}
# Is this file in home page folder?
if {![string match ${homePagePath}* $files]} {
alertnote "'[file tail $files]' is not in the home page folder."
return
}
# Make it a list in case it contains spaces.
set files [list $files]
} elseif {$where == "folder"} {
if {[catch {get_directory -p "Folder to scan."} folder]} {return}
set folder [string trimright $folder :]
# Is this folder in home page folder?
if {![string match ${homePagePath}* $folder]} {
alertnote "'[file tail $folder]' is not in the home page folder."
return
}
set files [htmlGetHTMLfiles $folder]
} else {
set files [htmlAllHTMLfiles]
}
htmlScanFiles $files 1
}
# Returns a list of all HTML files in home page folder.
proc htmlAllHTMLfiles {} {
global homePagePath
message "Building file listノ"
set folders [list $homePagePath]
while {[llength $folders]} {
set newFolders ""
foreach fl $folders {
append files " " [htmlGetHTMLfiles $fl]
# Get folders in this folder.
if {![catch {glob "$fl:*"} filelist]} {
foreach fil $filelist {
if {[file isdirectory $fil]} {
lappend newFolders $fil
}
}
}
}
set folders $newFolders
}
return $files
}
# Finds all HTML files in a folder
proc htmlGetHTMLfiles {folder} {
global filepats
set files ""
if {![catch {glob -t TEXT $folder:*} filelist]} {
foreach fil $filelist {
foreach suffix $filepats(HTML) {
if {[string match $suffix $fil]} {
lappend files $fil
break
}
}
}
}
return $files
}
# checking = 1: called from htmlCheckLinks
# Scan a list of files for HTML links and check if they point to existing files.
# Some code is taken from grep.tcl
# checking = 0: called from htmlMoveFiles
# Build a list of links which point to the files just moved.
proc htmlScanFiles {files checking {movedFiles ""}} {
global htmlURLAttr homePagePath winModes
global tileLeft tileTop tileWidth errorHeight
# Build regular expressions with URL attrs.
set exp "¥[ ¥¥t¥¥n¥¥r¥]+("
foreach attr $htmlURLAttr {
append exp "$attr|"
}
set exp [string trimright $exp |]
append exp ")"
set expBase "<base¥[ ¥¥t¥¥n¥¥r¥]+¥[^>¥]*>"
set expBase2 "(href=)¥"?(¥[^ ¥¥t¥¥n¥¥r¥">¥]+)¥"?"
set exprr "$exp¥"?(¥[^ ¥¥t¥¥n¥¥r¥">¥]+)¥"?"
set lines ""
foreach f $files {
if {![catch {set fid [open $f]}]} {
set extraPath ""
set baseText ""
set thisURL [string range [file dirname $f] ¥
[expr [string length $homePagePath] + 1] end]
message "Looking at [file tail $f]ノ"
set filecont [read $fid]
close $fid
if {[regexp {¥n} $filecont]} {
set newln "¥n"
} else {
set newln "¥r"
}
# Look for BASE.
if {[regexp -nocase $expBase $filecont thisLine]} {
if {[regexp -nocase $expBase2 $thisLine href b url]} {
set extra [htmlPathFromBASE $url]
set extraPath [lindex $extra 0]
set thisURL [string range [file dirname [lindex $extra 1]] ¥
[expr [string length $homePagePath] + 1] end]
set baseText "(BASE used) "
}
}
set linenum 1
# Find all links in every line.
while {[regexp -nocase -indices $exprr $filecont href b url]} {
incr linenum [regsub -all $newln [string range $filecont 0 [lindex $url 0]] {} dummy]
set l [expr 20 - [string length [file tail $f]]]
set ln [expr 5 - [string length $linenum]]
set href [string trim [string range $filecont [lindex $href 0] [lindex $href 1]]]
set linkTo [string range $filecont [lindex $url 0] [lindex $url 1]]
# Check if link begins with string from BASE to home page, or is absolute.
if {[string match "$extraPath*" $linkTo] || [regexp {://} $linkTo]} {
# Remove extraPath if link is not absolute.
if {![regexp {://} $linkTo]} {
set linkTo [string range $linkTo [string length $extraPath] end]
}
set linkToPath [htmlPathToFile $thisURL $linkTo]
# If this is BASE HREF, ignore it.
if {[string length $baseText] && [regexp -nocase -indices $expBase $filecont thisLine] ¥
&& [regexp -nocase $expBase2 [string range $filecont [lindex $thisLine 0] [lindex $thisLine 1]]]¥
&& [lindex $thisLine 0] < [lindex $url 0] && [lindex $thisLine 1] > [lindex $url 1]} {
set linkToPath ""
}
} else {
set linkToPath ""
}
set filecont [string range $filecont [lindex $url 1] end]
if {$checking} {
# Does the file exist? Ignore it if it's outside home page folder.
# Then it point to someone else's home page.
if {[string match "$homePagePath*" $linkToPath] && ![file exists $linkToPath]} {
append lines "[string range $f [expr [string length $homePagePath] + 1] end]"¥
"[format "%$l¥s" ""]; Line $linenum:[format "%$ln¥s" ""]$baseText$href"¥
"¥t¥t¥t¥t¥t¥t¥t¥t¥t¥t¥t¥t¥t¥t¥t¥t¥t¥t¥t¥t¥t¥t¥tー$f¥r"
}
} else {
if {[lsearch -exact $movedFiles $linkToPath] >=0 } {
if {[string length $thisURL]} {
set dum ":dummy"
} else {
set dum dummy
}
lappend toModify [list $f $linenum $extraPath "$homePagePath:${thisURL}$dum" $linkToPath $href]
}
}
}
}
}
if {$checking} {
if {[string length $lines]} {
new -n "* Invalid URLs *" -g $tileLeft $tileTop $tileWidth $errorHeight
set name [lindex [winNames] 0]
changeMode [set winModes($name) Brws]
insertText "Links to non-existing files: (<cr> to go to file)¥r¥r"
insertText $lines
select [nextLineStart [nextLineStart 0]] [nextLineStart [nextLineStart [nextLineStart 0]]]
setWinInfo dirty 0
setWinInfo read-only 1
} else {
alertnote "All links are OK."
}
} else {
if {[info exists toModify]} {
return $toModify
} else {
return ""
}
}
}
# Determine the path to the file "to", as linked from "from". Returns empty string if
# "to" is a link outside the home page.
proc htmlPathToFile {from to} {
global homePagePath HTMLmodeVars
set baseURL $HTMLmodeVars(baseURL)
set basePath $HTMLmodeVars(basePath)
# Remove anchor from "to".
regexp {[^#]*} $to to
# Remove ./ from path
if {[string range $to 0 1] == "./"} {set to [string range $to 2 end]}
# Relative URL beginning with / is relative to server URL.
if {[string range $to 0 0] == "/"} {
set to "$baseURL[string range $to 1 end]"
}
# Is this a absolute URL somewhere else or a mailto URL?
if {([regexp {://} $to] && ![string match "$baseURL$basePath*" $to]) ¥
|| [string match "mailto:*" [string tolower $to]]} {
return
}
# Absolut URL within the home page?
if {[string match "$baseURL$basePath*" $to]} {
set to [string range $to [expr [string length $baseURL] + ¥
[string length $basePath]] end]
set from ""
}
set fromPath [split $from :]
set toPath [split $to /]
# Back down for every ../
foreach tp $toPath {
if {$tp == ".."} {
if {[llength $fromPath]} {
set fromPath [lrange $fromPath 0 [expr [llength $fromPath] - 2]]
set toPath [lrange $toPath 1 end]
} else {
# this link points outside the home page.
return
}
} else {
break
}
}
set path ""
# Add path to file linked from.
if {[llength $fromPath]} {append path "[join $fromPath :]:"}
# Add path to file linked to.
append path [join $toPath :]
set path [string trimright $path :]
# If link to folder, add index.html.
if {[file isdirectory "${homePagePath}:$path"]} {
if {[string length $path]} {append path :}
append path "index.html"
}
return "${homePagePath}:$path"
}
# Moves files from one folder to another and update all links to the moved files
# as well as all links in the moved files.
proc htmlMoveFiles {} {
global homePagePath HTMLmodeVars htmlURLAttr
# Check that homePagePath is set.
if {[catch htmlIsThereHomePage]} {return}
# Remove ending :, otherwise it will all be a mess.
set homePagePath [string trimright $homePagePath :]
# Check that the server URL is set.
if {[catch {htmlIsThereBaseURL "You must set the Server URL."}]} {return}
set baseURL $HTMLmodeVars(baseURL)
set basePath $HTMLmodeVars(basePath)
if {[askyesno "All windows must be saved before you can moves files. Save?"] == "no"} {return}
saveAll
# Get folder to move from.
if {[catch {get_directory -p "Move from."} fromFolder]} {return}
set fromFolder [string trimright $fromFolder :]
# Is this folder in home page folder?
if {![string match ${homePagePath}* $fromFolder]} {
alertnote "'[file tail $fromFolder]' is not in the home page folder."
return
}
# Get files to move.
if {![catch {glob "$fromFolder:*"} files]} {
foreach f $files {
if {![file isdirectory $f]} {
lappend filelist [file tail $f]
}
}
} else {
return
}
if {[catch {listpick -p "Select files to move." -l $filelist} movefiles] || ¥
![string length $movefiles]} {return}
# Get folder to move to.
if {[catch {get_directory -p "Move to."} toFolder]} {return}
set toFolder [string trimright $toFolder :]
if {$fromFolder == $toFolder} {
alertnote "This is the same folder as you moved from."
return
}
# Is this folder in home page folder?
if {![string match ${homePagePath}* $toFolder]} {
alertnote "'[file tail $toFolder]' is not in the home page folder."
return
}
# Move the files.
foreach f $movefiles {
if {[file exists "$toFolder:$f"]} {
if {[askyesno "Replace '$f' in folder '[file tail $toFolder]'?"] == "yes"} {
removeFile "$toFolder:$f"
} else {
continue
}
}
foreach w [winNames -f] {
set ww $w
regexp {(.*) <[0-9]+>} $w dummy w
if {$w == "$fromFolder:$f"} {
alertnote "'[file tail $ww]' must be closed before it can be moved. It will be reopened again."
bringToFront $ww
killWindow
lappend reOpen "$toFolder:$f"
}
}
lappend movedFiles "$fromFolder:$f"
lappend movedFiles2 "$toFolder:$f"
mv "$fromFolder:$f" "$toFolder:$f"
}
if {![info exists movedFiles] || [askyesno "Files have been moved. Update links?"] == "no"} {return}
set allfiles [htmlAllHTMLfiles]
foreach f $movedFiles2 {
if {[set i [lsearch -exact $allfiles $f]] >= 0} {
set allfiles [lreplace $allfiles $i $i]
}
}
# Build regular expressions with URL attrs.
set exp "("
foreach attr $htmlURLAttr {
append exp "$attr|"
}
set exp [string trimright $exp |]
append exp ")"
set expBase "<(base¥[ ¥¥t¥¥n¥¥r¥]+)¥[^>¥]*>"
set expBase2 "(href=)¥"?(¥[^ ¥¥t¥¥n¥¥r¥">¥]+)¥"?"
set exprr "$exp¥"?(¥[^ ¥¥t¥¥n¥¥r¥">¥]+)¥"?"
set exprr2 "¥[ ¥¥t¥¥n¥¥r¥]+$exp¥"?(¥[^ ¥¥t¥¥n¥¥r¥">¥]+)¥"?"
# Update links to the moved files.
set toModify [htmlScanFiles $allfiles 0 $movedFiles]
set num 0
if {[llength $toModify]} {
set thisfile ""
foreach modify $toModify {
set fil [lindex $modify 0]
if {$thisfile != $fil} {
if {[string length $thisfile]} {
set fid [open $thisfile w]
puts -nonewline $fid [join $filecont "¥r"]
close $fid
}
message "Modifying [file tail $fil]ノ"
foreach w [winNames -f] {
set ww $w
regexp {(.*) <[0-9]+>} $w dummy w
if {$w == "$fil"} {
lappend changed $ww
}
}
set fid [open $fil r]
incr num
set filec [read $fid]
close $fid
if {[regexp {¥n} $filec]} {
set newln "¥n"
} else {
set newln "¥r"
}
set filec [split $filec $newln]
set filecont ""
foreach fc $filec {
lappend filecont [string trimleft $fc "¥r"]
}
}
set thisfile $fil
set linenum [expr [lindex $modify 1] - 1]
set line [lindex $filecont $linenum]
set path [lindex $movedFiles2 [lsearch -exact $movedFiles [lindex $modify 4]]]
set linkTo "[lindex $modify 2][htmlRelativePath [lindex $modify 3] $path]"
regexp -indices [lindex $modify 5] $line href
regexp -nocase -indices $exprr [string range $line [lindex $href 0] [lindex $href 1]] a b url
set anchor ""
regexp {[^#]*(#[^¥"]*)} [lindex $modify 5] a anchor
set line "[string range $line 0 [expr [lindex $href 0] + [lindex $url 0] - 1]]$linkTo$anchor[string range $line [expr [lindex $href 0] + [lindex $url 1] + 1] end]"
set filecont [lreplace $filecont $linenum $linenum $line]
}
set fid [open $thisfile w]
puts -nonewline $fid [join $filecont "¥r"]
close $fid
}
# Modify links in moved files.
foreach f $movedFiles2 {
getFileInfo $f finfo
if {$finfo(type) != "TEXT"} {continue}
message "Modifying [file tail $f]ノ"
set fid [open $f r]
set filecont [read $fid]
close $fid
set oldfile [lindex $movedFiles [lsearch -exact $movedFiles2 $f]]
# Replace newline chars in IBM files.
regsub -all "¥[¥r¥n¥]+" $filecont "¥r" filecont
# If BASE is used, only modify links to moved files.
if {[regexp -nocase $expBase $filecont this] && ¥
[regexp -nocase $expBase2 $this d1 d2 url1]} {
set hasBase 1
} else {
set hasBase 0
}
set f0 $f
if {$hasBase} {
set extra [htmlPathFromBASE $url1]
set extraPath [lindex $extra 0]
set oldfile "[file dirname [lindex $extra 1]]:[file tail $oldfile]"
set f $oldfile
} else {
set extraPath ""
}
incr num
set newcont ""
while {[regexp -nocase -indices $exprr2 $filecont href b url]} {
set urltxt [string range $filecont [lindex $url 0] [lindex $url 1]]
set anchor ""
regexp {[^#]*(#[^¥"]*)} $urltxt a anchor
if {[string match "$extraPath*" $urltxt] || [regexp {://} $urltxt]} {
if {![regexp {://} $urltxt]} {
set urltxt [string range $urltxt [string length $extraPath] end]
}
set path [htmlPathToFile [string range [file dirname $oldfile] ¥
[expr [string length $homePagePath] + 1] end] $urltxt]
# Is the link pointing to a previously moved file?
if {[set mvind [lsearch -exact $movedFiles $path]] >= 0} {
set path [lindex $movedFiles2 $mvind]
}
if {$hasBase && [regexp -nocase -indices $expBase $filecont thisLine] ¥
&& [regexp -nocase $expBase2 [string range $filecont [lindex $thisLine 0] [lindex $thisLine 1]]]¥
&& [lindex $thisLine 0] < [lindex $url 0] && [lindex $thisLine 1] > [lindex $url 1]} {
set path ""
}
} else {
set path ""
}
if {[string length $path]} {
set newurl "$extraPath[htmlRelativePath $f $path]$anchor"
} elseif {!$hasBase && ($urltxt == ".." || [string range $urltxt 0 2] == "../")} {
# Special case with relative links outside home page.
set urlspl [split $urltxt /]
set old [split $oldfile :]
set new [split $f :]
if {[llength $new] > [llength $old]} {
set newurl ""
for {set i 0} {$i < [expr [llength $new] - [llength $old]]} {incr i} {
append newurl "../"
}
append newurl $urltxt
} else {
set ok 1
for {set i 0} {$i < [expr [llength $old] - [llength $new]]} {incr i} {
if {[lindex $urlspl $i] != ".."} {set ok 0}
}
if {$ok} {
set newurl "[join [lrange $urlspl [expr [llength $old] - [llength $new]] end] /]$anchor"
} else {
set newurl $urltxt
}
}
} else {
set newurl $urltxt
}
append newcont [string range $filecont 0 [expr [lindex $url 0] - 1]]
append newcont $newurl
set filecont [string range $filecont [expr [lindex $url 1] + 1] end]
}
append newcont $filecont
set fid [open $f0 w]
puts -nonewline $fid $newcont
close $fid
}
message "$num files has been modified including the ones moved."
if {[info exists reOpen] && [askyesno "Reopen previously closed windows?"] == "yes"} {
foreach r $reOpen {
edit $r
}
}
if {[info exists changed] && [askyesno "Revert modified windows?"] == "yes"} {
foreach r $changed {
bringToFront $r
revert
}
}
}
#
# dividing line
#
proc htmlDividingLine {} {
global HTMLmodeVars fillColumn
set wordWrap $HTMLmodeVars(wordWrap)
set prefixString $HTMLmodeVars(prefixString)
set suffixString $HTMLmodeVars(suffixString)
set s "===================================================================================="
set l [expr [string length $prefixString] + [string length $suffixString]]
if {$wordWrap} {
set l [expr $fillColumn - $l - 1]
} else {
set l [expr 75 - $l - 1]
}
insertText [htmlOpenCR] $prefixString [string range $s 0 $l] $suffixString "¥r"
}
#
# Carriage returns and tabs (much borrowed from latex.tcl)
#
# A boolean function which takes any string and tests to see if
# that string contains all whitespace characters. Carriage returns
# are considered whitespace, as are spaces and tabs.
proc htmlIsWhite {anyString} {
set len [string length $anyString]
for {set i 0} {$i < $len} {incr i} {
set c [string index $anyString $i]
if {($c != "¥ ") && ($c != "¥t") && ($c != "¥r")} then {return 0}
}
return 1
}
# Insert one or two carriage returns at the insertion point if any
# character preceding the insertion point (on the same line)
# is a non-whitespace character.
proc htmlOpenCR {{extrablankline 0}} {
set end [getPos]
set start [lineStart $end]
set text [getText $start $end]
if {![htmlIsWhite $text]} {
set r "¥r"
if {$extrablankline} {append r "¥r"}
return $r
} elseif {$start > 0 } {
set prevstart [lineStart [expr $start - 1 ]]
set text [getText $prevstart [expr $start - 1]]
if {![htmlIsWhite $text] && $extrablankline} {
return "¥r"
} else {
return
}
} else {
return
}
}
# Insert a carriage return at the insertion point if any
# character following the insertion point (on the same line)
# is a non-whitespace character.
proc htmlCloseCR {} {
set start [getPos]
set end [nextLineStart $start]
set text [getText $start $end]
if {![htmlIsWhite $text]} {
return "¥r"
} else {
return
}
}
# Set up tab mark mechanism.
proc htmlTabGoto {directionIndicator} {
set searchResult [search -s -n -f $directionIndicator -m 0 -i 1 -r 0 {・} [getPos]]
if {![llength $searchResult] || [lindex $searchResult 0] >= [maxPos]} {
beep
message "Tab mark not found."
return 0
} else {
goto [lindex $searchResult 0]
return 1
}
}
proc htmlTabNext {} {
if {[htmlTabGoto 1]} {deleteChar}
}
proc htmlTabPrev {} {
if {[htmlTabGoto 0]} {deleteChar}
}
# Removes all tab marks from the current selection (if there is one)
# or the current document, maintaining the cursor position in the
# latter case. Stolen from latexMacros.tcl written by Tom Scavo.
proc htmlTabDeleteAll {} {
set subs1 0; set subs2 0; set subs3 0
set pos [getPos]
if {[set start $pos] == [set end [selEnd]]} {
set messageString "document"
set start 0
set end [maxPos]
set text1 [getText $start $pos]
set subs1 [regsub -all {・} $text1 {} text1]
set text2 [getText $pos $end]
set subs2 [regsub -all {・} $text2 {} text2]
append text $text1 $text2
} else {
set messageString "selection"
set text [getText $start $end]
set subs3 [regsub -all {・} $text {} text]
}
if {$subs1 || $subs2 || $subs3} then {
replaceText $start $end $text
if {$messageString == "document"} then {
goto [expr $pos - $subs1]
} else {
set end [getPos]
select $start $end
}
set subs [expr $subs1 + $subs2 + $subs3]
message "$subs tab marks removed from $messageString."
} else {
message "No tab marks found in $messageString."
}
}
#
# Converting characters to HTML entities.
#
proc htmlCharacterstohtml {} {
global htmlSpecialCharacter
global htmlSpecialCapCharacter htmlSpecialSymbCharacter
message "Translatingノ"
foreach a [array names htmlSpecialCharacter] {
if { $a != "eth" && $a != "thorn" && $a != "yォ"} {
lappend charlist $a
}
}
foreach a [array names htmlSpecialCapCharacter] {
if {$a != "ETH" && $a != "THORN" && $a != "Yォ"} {
lappend charlist $a
}
}
lappend charlist チ タ
set subs1 0; set lett 0
set pos [getPos]
if {[set start $pos] == [set end [selEnd]]} {
set messageString "document"
set start 0
set end [maxPos]
set text1 [getText $start $pos]
set text2 [getText $pos $end]
set isDoc 1
} else {
set messageString "selection"
set text1 [getText $start $end]
set isDoc 0
}
foreach char $charlist {
if {[info exists htmlSpecialCharacter($char)]} {
set rtext "¥¥&$htmlSpecialCharacter($char);"
} elseif {[info exists htmlSpecialCapCharacter($char)]} {
set rtext "¥¥&$htmlSpecialCapCharacter($char);"
} else {
set rtext "¥¥&$htmlSpecialSymbCharacter($char);"
}
set subNum [regsub -all $char $text1 [set rtext] text1]
incr subs1 [expr $subNum * ([string length $rtext] - 2)]
incr lett $subNum
if {$isDoc} {
set subNum [regsub -all $char $text2 [set rtext] text2]
incr lett $subNum
}
}
set text $text1
if {$isDoc} {append text $text2}
if {$lett} {
replaceText $start $end $text
if {$isDoc} {
goto [expr $pos + $subs1]
} else {
set end [getPos]
select $start $end
}
}
message "$lett characters translated in $messageString."
}
#
# Converting HTML entities to characters.
#
proc htmltoCharacters {} {
global htmlCharacterSpecial
global htmlCapCharacterSpecial
message "Translatingノ"
foreach a [array names htmlCharacterSpecial] {
if { $a != "eth" && $a != "thorn" && $a != "yォ"} {
lappend entitylist "&$a;"
}
}
foreach a [array names htmlCapCharacterSpecial] {
if {$a != "ETH" && $a != "THORN" && $a != "Yォ"} {
lappend entitylist "&$a;"
}
}
# チ タ
lappend entitylist "¡" "¿"
set subs1 0; set lett 0
set pos [getPos]
if {[set start $pos] == [set end [selEnd]]} {
# Move position to linestart to make sure no letter is split.
set pos [lineStart $pos]
set messageString "document"
set start 0
set end [maxPos]
set text1 [getText $start $pos]
set text2 [getText $pos $end]
set isDoc 1
} else {
set messageString "selection"
set text1 [getText $start $end]
set isDoc 0
}
foreach char $entitylist {
set schar [string range $char 1 [expr [string length $char] - 2]]
if {[info exists htmlCharacterSpecial($schar)]} {
set rtext "$htmlCharacterSpecial($schar)"
} elseif {[info exists htmlCapCharacterSpecial($schar)]} {
set rtext "$htmlCapCharacterSpecial($schar)"
} elseif {$schar == "#161"} {
set rtext チ
} elseif {$schar == "#191"} {
set rtext タ
}
set subNum [regsub -all $char $text1 $rtext text1]
incr subs1 [expr $subNum * ([string length $char] - 1)]
incr lett $subNum
if {$isDoc} {
set subNum [regsub -all $char $text2 $rtext text2]
incr lett $subNum
}
}
set text $text1
if {$isDoc} {append text $text2}
if {$lett} {
replaceText $start $end $text
if {$isDoc} {
goto [expr $pos - $subs1]
} else {
set end [getPos]
select $start $end
}
}
message "$lett characters translated in $messageString."
}
# Puts up a window with error text.
proc htmlErrorWindow {errHeader errText {cancelButton 0}} {
set errbox "-t {$errHeader} 100 10 400 25"
set hpos 35
foreach err $errText {
lappend errbox -t $err 10 $hpos 400 [expr $hpos + 15]
incr hpos 20
}
if {$cancelButton} {
lappend errbox -b Cancel 125 [expr $hpos + 20 ] 190 [expr $hpos + 40 ]
}
set val [eval [concat dialog -w 430 -h [expr $hpos + 60 ] ¥
-b OK 40 [expr $hpos + 20 ] 105 [expr $hpos + 40 ] $errbox]]
return [lindex $val 0]
}
#===============================================================================
# Building tags, including element attributes
#===============================================================================
# Six functions to get element variables from the right package.
proc htmlGetRequired {item} {
global htmlPackageToUse
global htmlElemAttrRequired1 htmlElemAttrRequired3
if {[catch {set reqatts [set htmlElemAttrRequired${htmlPackageToUse}($item)]}]} { set reqatts {} }
return $reqatts
}
proc htmlGetOptional {item} {
global htmlPackageToUse
global htmlElemAttrOptional1 htmlElemAttrOptional3
if {[catch {set optatts [set htmlElemAttrOptional${htmlPackageToUse}($item)]}]} { set optatts {} }
return $optatts
}
proc htmlGetNumber {item} {
global htmlPackageToUse
global htmlElemAttrNumber1 htmlElemAttrNumber3
if {[catch {set numatts [set htmlElemAttrNumber${htmlPackageToUse}($item)]}]} { set numatts {} }
return $numatts
}
proc htmlGetChoices {item} {
global htmlPackageToUse
global htmlElemAttrChoices1 htmlElemAttrChoices3
if {[catch {set choiceatts [set htmlElemAttrChoices${htmlPackageToUse}($item)]}]} { set choiceatts {} }
return $choiceatts
}
proc htmlGetUsed {item} {
global htmlPackageToUse
global htmlElemAttrUsed htmlElemAttrUsed3
if {$htmlPackageToUse == 1} {
set num ""
} else {
set num 3
}
if {[catch {set useatts [set htmlElemAttrUsed${num}($item)]}]} { set useatts {} }
return $useatts
}
proc htmlGetAttrMore {item} {
global htmlPackageToUse
global htmlElemAttrMore htmlElemAttrMore3
if {$htmlPackageToUse == 1} {
set num ""
} else {
set num 3
}
if {[catch {set askformore [set htmlElemAttrMore${num}($item)]}]} { set askformore 0 }
return $askformore
}
proc htmlOpenElem {elem {used ""}} {
global HTMLmodeVars
if {$HTMLmodeVars(useBigWindows)} {
return [htmlOpenElemWindow $elem $used]
} else {
return [htmlOpenElemLoop $elem $used]
}
}
# Opening or only tag of an element - include attributes
# Big window with all attributes.
# Return empty string if user clicks "Cancel".
proc htmlOpenElemWindow {elem used {values ""}} {
global HTMLmodeVars htmlColorName htmlElemEventHandler1
global htmluserColors basicColors htmlPackageToUse
global htmlURLAttr htmlColorAttr htmlWindowAttr
global htmlSpecURL htmlSpecColor htmlSpecWindow
set URLs $HTMLmodeVars(URLs)
set Windows $HTMLmodeVars(windows)
# put users colours first
set htmlColors [lsort [array names htmluserColors]]
append htmlColors " " $basicColors
if {![string length $used]} {set used $elem}
set elem [string toupper $elem]
set used [string toupper $used]
# get variables for the element
set reqatts [htmlGetRequired $used]
set numatts [htmlGetNumber $used]
set optatts [htmlGetOptional $used]
set choiceatts [htmlGetChoices $used]
set allatts [concat $reqatts $optatts]
# optionally include event handlers
if {$HTMLmodeVars(inclEventHandler) && $htmlPackageToUse == 1 && ¥
[info exists htmlElemEventHandler1($used)]} {
set eventatts $htmlElemEventHandler1($used)
append allatts " " $eventatts
} else {
set eventatts ""
}
# if there are attributes to ask about, do so
set text "<"
append text [htmlSetCase $elem]
set maxHeight [expr [lindex [getMainDevice] 3] - 115]
set thisPage "Page 1"
if {[llength $allatts]} {
# build window with attributes
set invalidInput 1
while {$invalidInput} {
while {1} {
if {$used == "LI IN UL" || $used == "LI IN OL"} {
set pr LI
} else {
set pr $used
}
set box1 "-t {Attributes for $pr} 120 10 320 25"
set box2 "-t {Attributes for $pr} 120 10 320 25"
set box3 "-t {Attributes for $pr} 120 10 320 25"
set page 1
set attrtypes {}
set fileIndex ""
set colorIndex ""
set wpos 10
if {[string length $reqatts]} {
lappend box$page -p 120 30 270 31 -t {Required attributes} 10 35 200 50
set hpos 60
} else {
set hpos 30
}
set attrIndex 2
for {set i 0} {$i < [llength $allatts]} {incr i} {
set attr [lindex $allatts $i]
if {$i == [llength $reqatts]} {
if {$wpos > 20} { incr hpos 20 }
lappend box$page -p 120 $hpos 270 [expr $hpos + 1] ¥
-t {Optional attributes} 10 [expr $hpos + 5] 200 [expr $hpos + 20]
set wpos 10
incr hpos 30
}
set a2 [string trimright $attr =]
if {([lsearch -exact $htmlURLAttr $attr] >= 0 && [lsearch -exact $htmlSpecURL "${used}!=$a2"] < 0) || ¥
[lsearch -exact $htmlSpecURL "${used}=$a2"] >= 0} {
# URL
if {$wpos > 20} { incr hpos 25 ; set wpos 10}
if {[expr $hpos + 45] > $maxHeight && $page < 3} {
incr page
set hpos 40
}
if {[llength values]} {
set etxt [lindex $values $attrIndex]
set mtxt [lindex $values [expr $attrIndex + 1]]
incr attrIndex 3
} else {
set etxt ""
set mtxt {No value}
}
lappend box$page -t $attr 10 $hpos 120 [expr $hpos + 15] ¥
-e $etxt 120 $hpos 450 [expr $hpos + 15] ¥
-m [concat [list $mtxt {No value}] $URLs] ¥
120 [expr $hpos + 25] 450 [expr $hpos + 35] ¥
-b "Fileノ" 10 [expr $hpos + 20] 70 [expr $hpos + 40]
incr hpos 50
lappend attrtypes url
lappend fileIndex [expr $attrIndex - 1]
} elseif {([lsearch -exact $htmlColorAttr $attr] >= 0 && [lsearch -exact $htmlSpecColor "${used}!=$a2"] < 0) || ¥
[lsearch -exact $htmlSpecColor "${used}=$a2"] >= 0} {
# Color attribute
if {$wpos > 20} { incr hpos 25 ; set wpos 10}
if {[expr $hpos + 25] > $maxHeight && $page < 3} {
incr page
set hpos 40
}
if {[llength values]} {
set etxt [lindex $values $attrIndex]
set mtxt [lindex $values [expr $attrIndex + 1]]
incr attrIndex 3
} else {
set etxt ""
set mtxt {No value}
}
lappend box$page -t $attr 10 $hpos 120 [expr $hpos + 15] ¥
-e $etxt 120 $hpos 190 [expr $hpos + 15] ¥
-m [concat [list $mtxt {No value}] $htmlColors] ¥
200 $hpos 340 [expr $hpos + 15] ¥
-b "New Colorノ" 350 $hpos 450 [expr $hpos + 20]
incr hpos 30
lappend attrtypes color
lappend colorIndex [expr $attrIndex - 1]
} elseif {([lsearch -exact $htmlWindowAttr $attr] >= 0 && [lsearch -exact $htmlSpecWindow "${used}!=$a2"] < 0) || ¥
[lsearch -exact $htmlSpecWindow "${used}=$a2"] >= 0} {
# Window attribute
if {$wpos > 20} { incr hpos 25 ; set wpos 10}
if {[expr $hpos + 25] > $maxHeight && $page < 3} {
incr page
set hpos 40
}
if {[llength values]} {
set etxt [lindex $values $attrIndex]
set mtxt [lindex $values [expr $attrIndex + 1]]
incr attrIndex 2
} else {
set etxt ""
set mtxt {No value}
}
lappend box$page -t $attr 10 $hpos 120 [expr $hpos + 15] ¥
-e $etxt 120 $hpos 240 [expr $hpos + 15] ¥
-m [concat [list $mtxt {No value}] ¥
[concat {_SELF _TOP _PARENT _BLANK} $Windows]] ¥
250 $hpos 440 [expr $hpos + 15]
incr hpos 30
lappend attrtypes window
} elseif {[lsearch $numatts "${attr}*"] >= 0} {
# Number
if {[expr $hpos + 20] > $maxHeight && $wpos < 20 && $page < 3} {
incr page
set hpos 40
}
if {[llength values]} {
set etxt [lindex $values $attrIndex]
incr attrIndex
} else {
set etxt ""
}
lappend box$page -t $attr $wpos $hpos [expr $wpos + 100] [expr $hpos + 15] ¥
-e $etxt [expr $wpos + 110] $hpos [expr $wpos + 150] [expr $hpos + 15]
if {$wpos > 20} {
incr hpos 25
set wpos 10
} else {
set wpos 230
}
lappend attrtypes number
} elseif {[string match "*${attr}*" $choiceatts] && [string index $attr [expr [string length $attr] - 1]] == "="} {
# Choices
if {[expr $hpos + 20] > $maxHeight && $wpos < 20 && $page < 3} {
incr page
set hpos 40
}
set matches {}
foreach w $choiceatts {
if {[string match "${attr}*" $w]} {
lappend matches [string range $w [string length $attr] end]
}
}
if {[llength values]} {
set mtxt [lindex $values $attrIndex]
incr attrIndex
} else {
set mtxt {No value}
}
lappend box$page -t $attr $wpos $hpos [expr $wpos + 100] [expr $hpos + 15] ¥
-m [concat [list $mtxt {No value}] $matches] ¥
[expr $wpos + 110] $hpos [expr $wpos + 205] [expr $hpos + 15]
if {$wpos > 20} {
incr hpos 25
set wpos 10
} else {
set wpos 230
}
lappend attrtypes choices
} elseif {[string index $attr [expr [string length $attr] - 1]] == "="} {
# Any other
if {$wpos > 20} { incr hpos 25 ; set wpos 10}
if {[expr $hpos + 20] > $maxHeight && $page < 3} {
incr page
set hpos 40
}
if {[llength values]} {
set etxt [lindex $values $attrIndex]
incr attrIndex
} else {
set etxt ""
}
lappend box$page -t $attr 10 $hpos 120 [expr $hpos + 15] ¥
-e $etxt 120 $hpos 450 [expr $hpos + 15]
incr hpos 25
lappend attrtypes any
} else {
# Flag
if {[expr $hpos + 20] > $maxHeight && $wpos < 20 && $page < 3} {
incr page
set hpos 40
}
if {[llength values]} {
set ctxt [lindex $values $attrIndex]
incr attrIndex
} else {
set ctxt 0
}
lappend box$page -c $attr $ctxt $wpos $hpos [expr $wpos + 100] [expr $hpos + 15]
if {$wpos > 20} {
incr hpos 25
set wpos 10
} else {
set wpos 230
}
lappend attrtypes flag
}
}
if {$wpos > 20} { incr hpos 25 }
if {$page == 1} {
set box $box1
} elseif {$page == 2} {
set hpos $maxHeight
set box " -m ¥{¥{$thisPage¥} ¥{Page 1¥} ¥{Page 2¥}¥} 10 10 85 30 -n ¥{Page 1¥} $box1 -n ¥{Page 2¥} $box2"
} elseif {$page == 3} {
set hpos $maxHeight
set box " -m ¥{¥{$thisPage¥} ¥{Page 1¥} ¥{Page 2¥} ¥{Page 3¥}¥} 10 10 85 30 -n ¥{Page 1¥} $box1 -n ¥{Page 2¥} $box2 -n ¥{Page 3¥} $box3"
}
set values [eval [concat dialog -w 460 -h [expr $hpos + 50] ¥
-b OK 20 [expr $hpos + 20] 85 [expr $hpos + 40] ¥
-b Cancel 110 [expr $hpos + 20] 175 [expr $hpos + 40] $box]]
# If two pages...
if {$page > 1} {
set thisPage [lindex $values 2]
set values [lreplace $values 2 2]
}
# OK button clicked?
if {[lindex $values 0] } { break }
# Cancel button clicked?
if {[lindex $values 1] } { return}
# File button clicked?
foreach fl $fileIndex {
if {[lindex $values $fl]} {
set newFile [htmlGetFile]
if {[string length $newFile]} {
set URLs $HTMLmodeVars(URLs)
set values [lreplace $values [expr $fl - 1] [expr $fl - 1] $newFile]
}
}
}
# Color button clicked?
foreach cl $colorIndex {
if {[lindex $values $cl]} {
set newcolor [htmlAddNewColor]
if {[string length $newcolor]} {
set htmlColors [concat [list $newcolor] $htmlColors]
set values [lreplace $values [expr $cl - 1] [expr $cl - 1] "$newcolor"]
}
}
}
}
# put everything together
set attrtext ""
set errtext ""
if {[lindex $values 0]} {
set j 2
for {set i 0} {$i < [llength $attrtypes]} {incr i} {
set attr [lindex $allatts $i]
switch [lindex $attrtypes $i] {
url {
set texturl [string trim [lindex $values $j]]
set menuurl [lindex $values [expr $j + 1]]
if {[string length $texturl]} {
append attrtext " " [htmlSetCase $attr] ¥
[htmlAddQuotes $texturl]
htmlAddToCache URLs $texturl
} elseif {$menuurl != "No value"} {
append attrtext " " [htmlSetCase $attr] ¥
[htmlAddQuotes $menuurl]
} elseif {[lsearch -exact $reqatts $attr] >= 0} {
lappend errtext "$attr required."
}
incr j 3
}
color {
set colortxt [lindex $values $j]
set colorval [lindex $values [expr $j + 1]]
if {[string length $colortxt]} {
set col [htmlCheckColorNumber $colortxt]
if {$col == 0} {
lappend errtext "$attr: $colortxt is not a valid color number."
} else {
append attrtext " " [htmlSetCase $attr] ¥
[htmlAddQuotes $col]
}
} elseif {$colorval != "No value"} {
# Users own color?
if {[info exists htmluserColors($colorval)]} {
set colornum $htmluserColors($colorval)
}
# Predefined color?
if {[info exists htmlColorName($colorval)]} {
set colornum $htmlColorName($colorval)
}
append attrtext " " [htmlSetCase $attr] ¥
[htmlAddQuotes $colornum]
} elseif {[lsearch -exact $reqatts $attr] >= 0} {
lappend errtext "$attr required."
}
incr j 3
}
window {
set textwin [string trim [lindex $values $j]]
set menuwin [lindex $values [expr $j + 1]]
if {[string length $textwin]} {
append attrtext " " [htmlSetCase $attr] ¥
[htmlAddQuotes $textwin]
htmlAddToCache windows $textwin
} elseif {$menuwin != "No value"} {
append attrtext " " [htmlSetCase $attr] ¥
[htmlAddQuotes $menuwin]
} elseif {[lsearch -exact $reqatts $attr] >= 0} {
lappend errtext "$attr required."
}
incr j 2
}
number {
set numval [string trim [lindex $values $j]]
if {[string length $numval]} {
if {[htmlCheckAttrNumber $used $attr $numval] == 1} {
append attrtext " " [htmlSetCase $attr] ¥
[htmlAddQuotes $numval]
} else {
lappend errtext "$attr: [htmlCheckAttrNumber $used $attr $numval]"
}
} elseif {[lsearch -exact $reqatts $attr] >= 0} {
lappend errtext "$attr required."
}
incr j
}
choices {
set choiceval [lindex $values $j]
if {$choiceval != "No value"} {
append attrtext " " [htmlSetCase $attr]
set qchoice [htmlAddQuotes $choiceval]
if {($used != "LI IN OL" && $used != "OL") || $attr != "TYPE="} {
set qchoice [htmlSetCase $qchoice]
}
append attrtext $qchoice
} elseif {[lsearch -exact $reqatts $attr] >= 0} {
lappend errtext "$attr required."
}
incr j
}
any {
set anyval [lindex $values $j]
# Trim only if it's only spaces.
if {[string trim $anyval] == ""} {set anyval ""}
if {[string length $anyval]} {
if {[lsearch -exact $eventatts $attr] < 0} {
set attr [htmlSetCase $attr]
}
append attrtext " " $attr [htmlAddQuotes $anyval]
htmlOpenExtraThings $used $attr $anyval
} elseif {[lsearch -exact $reqatts $attr] >= 0} {
lappend errtext "$attr required."
}
incr j
}
flag {
set flagval [lindex $values $j]
if {$flagval} {
append attrtext " " [htmlSetCase $attr]
}
incr j
}
}
}
# If everything is OK, add the attribute text to text.
if {![llength $errtext]} {
append text $attrtext
set invalidInput 0
} else {
# Put up alert with the error text.
htmlErrorWindow "Invalid input for $used" $errtext
}
# Some tests that input is ok.
if {!$invalidInput} {set invalidInput [htmlFontBaseTest $text alertnote]}
if {!$invalidInput && $elem == "A" && [set invalidInput [htmlATest $text alertnote]]} {
set text "<[htmlSetCase A]"
}
if {!$invalidInput && $elem == "FRAMESET" && [set invalidInput [htmlFramesetTest $text alertnote]]} {
set text "<[htmlSetCase FRAMESET]"
}
if {!$invalidInput && $elem == "SPACER" && [set invalidInput [htmlSpacerTest $text alertnote]]} {
set text "<[htmlSetCase SPACER]"
}
if {!$invalidInput && $elem == "AREA" && [set invalidInput [htmlAreaTest $text alertnote]]} {
set text "<[htmlSetCase AREA]"
}
} else {
set text ""
}
}
}
if {[string length $text] } {append text ">"}
return ${text}
}
# these two require at least one of several optional attributes
proc htmlFontBaseTest {text cmd} {
if {([string toupper $text] == "<FONT" || [string toupper $text] == "<BASE" )} {
eval {$cmd "At least one of the attributes is required."}
return 1
}
return 0
}
# HREF or NAME must be used for A.
proc htmlATest {text cmd} {
if {![regexp -nocase {href=} $text] && ![regexp -nocase {name=} $text]} {
eval {$cmd "At least one of the attributes HREF and NAME must be used."}
return 1
}
return 0
}
# ROWS or COLS must be used for FRAMESET
proc htmlFramesetTest {text cmd} {
if {![regexp -nocase {rows=} $text] && ![regexp -nocase {cols=} $text]} {
eval {$cmd "At least one of the attributes ROWS and COLS must be used."}
return 1
}
return 0
}
# Some checks for SPACER.
proc htmlSpacerTest {text cmd} {
set horver [regexp -nocase {type=¥"(horizontal|vertical)¥"} $text]
set wh [regexp -nocase {width=|height=} $text]
set sz [regexp -nocase {size=} $text]
set al [regexp -nocase {align=} $text]
set invalidInput 1
if {$horver && ($wh || $al)} {
eval {$cmd "WIDTH, HEIGHT and ALIGN should only be used when TYPE=BLOCK."}
} elseif {!$horver && $sz} {
eval {$cmd "SIZE should only be used when TYPE=HORIZONTAL or VERTICAL."}
} elseif {$horver && !$sz} {
eval {$cmd "SIZE is required when TYPE=HORIZONTAL or VERTICAL."}
} elseif {!$horver && !$wh} {
eval {$cmd "WIDTH or HEIGHT is required when TYPE=BLOCK."}
} else {
set invalidInput 0
}
return $invalidInput
}
# For AREA, either HREF or NOHREF must be used, but not both.
proc htmlAreaTest {text cmd} {
set hasHref [regexp -nocase {href=} $text]
set hasNohref [regexp -nocase {nohref} $text]
set hasCoords [regexp -nocase {coords=} $text]
set shapeDefault [regexp -nocase {shape=¥"default¥"} $text]
set invalidInput 0
if {($hasHref && $hasNohref) || (!$hasHref && !$hasNohref)} {
eval {$cmd "One of the attributes HREF and NOHREF must be used, but not both."}
set invalidInput 1
} elseif {!$hasCoords && !$shapeDefault} {
eval {$cmd "COORDS= is required if SHAPEュDEFAULT"}
set invalidInput 1
}
return $invalidInput
}
# Adds a NAME= value to cache.
proc htmlOpenExtraThings {elem attr val} {
if {[lsearch -exact {A MAP} $elem] >= 0 && $attr == "NAME="} {
htmlAddToCache URLs "#$val"
}
if {$elem == "FRAME" && $attr == "NAME="} {
htmlAddToCache windows $val
}
}
# Check if a color number is a valid number.
# Returns 0 if not and the color number if it is.
proc htmlCheckColorNumber {color} {
if {[string range $color 0 0] != "#"} {
set color "#${color}"
}
set color [string toupper $color]
set testColor ""
regexp {^#[0-9A-F]+} [string range $color 0 end] testColor
if {[string length $color] != 7 || $testColor != $color} {
return 0
} else {
return $color
}
}
# Adds a URL or window given as input to cache
proc htmlAddToCache {cache newurl} {
global modifiedModeVars HTMLmodeVars
if {$cache == "windows" && [lsearch -exact {_SELF _TOP _PARENT _BLANK} [string toupper $newurl]] >= 0} {return}
set URLs $HTMLmodeVars($cache)
if {[string length $newurl] && [lsearch -exact $URLs $newurl] < 0} {
set URLs [lsort [lappend URLs $newurl]]
set HTMLmodeVars($cache) $URLs
lappend modifiedModeVars [list $cache HTMLmodeVars]
}
}
# Check if a input is a valid number for the element attribute.
# Returns 1 if it is, otherwise returns an error message.
proc htmlCheckAttrNumber {item attr number} {
set attrNumbers [htmlGetNumber $item]
set numind [lsearch $attrNumbers "${attr}*"]
set numstr [string range [lindex $attrNumbers $numind] [string length $attr] end]
regexp {^[-0-9]+} $numstr minvalue
set numstr [string range $numstr [expr [string length $minvalue] + 1] end]
regexp {^[-i0-9]+} $numstr maxvalue
set procent [string range $numstr [expr [string length $numstr] - 1] end]
if {$procent == "%"} {
set procerr " or percentage"
} else {
set procerr ""
}
if {$maxvalue == "i"} {
set errtext "A number $minvalue or greater"
} else {
set errtext "A number in the range $minvalue to $maxvalue"
}
if {$item == "FONT"} { append errtext " or -6 to +6"}
append errtext "$procerr expected."
# Is percent allowed?
if {[string index $number [expr [string length $number] - 1]] == "%" } {
set number [string range $number 0 [expr [string length $number] - 2]]
if {$procent != "%"} {return $errtext}
}
# FONT can take values -6 - +6. Special case.
if {$item == "FONT" && [regexp {^(¥+|-)[1-6]$} $number]} { return 1}
# Is input a number?
if {![regexp {^-?[0-9]+$} $number]} {return $errtext}
# Is input in the valid range?
if {( $maxvalue != "i" && $number > $maxvalue ) || $number < $minvalue } {
return $errtext
}
return 1
}
# Add quotes to attribute
proc htmlAddQuotes {v} {
if {[string range $v 0 0] != "¥""} {set v "¥"$v"}
set vlen [expr [string length $v] - 1]
if {[string range $v $vlen $vlen] !="¥""} {append v "¥""}
return $v
}
# Closing tag of an element
proc htmlCloseElem {theElem} {
set text ""
append text "</"
append text [htmlSetCase $theElem]
append text ">"
return $text
}
#
# Element build routines
#
# Build elements with only a opening tag.
proc htmlBuildOpening {ftype {begCR 0} {endCR 0} {attr ""}} {
set text1 ""
if {$begCR} { set text1 [htmlOpenCR]}
set text [htmlOpenElem $ftype $attr]
if {![string length $text]} {return}
if {$endCR} {append text "¥r"}
insertText $text1 $text
}
# This is used for almost all containers
proc htmlBuildElem {ftype {attr ""}} {
global HTMLmodeVars
set useTabMarks $HTMLmodeVars(useTabMarks)
global htmlCurSel
global htmlIsSel
set text [htmlOpenElem $ftype $attr]
# Check if user has skipped an attribute which can't be skipped.
if {![string length $text]} {return}
htmlGetSel
append text $htmlCurSel
set currpos [expr [getPos] + [string length $text]]
append text [htmlCloseElem $ftype]
if {!$htmlIsSel && $useTabMarks} {append text "・"}
if {$htmlIsSel} {
replaceText [getPos] [selEnd] $text
} else {
insertText $text
goto $currpos
}
}
# This is used for elements that should be surrounded by newlines
proc htmlBuildCRElem {ftype {extrablankline 0} {attr ""}} {
global htmlCurSel htmlIsSel
global HTMLmodeVars
set useTabMarks $HTMLmodeVars(useTabMarks)
set text [htmlOpenCR $extrablankline]
set text2 [htmlOpenElem $ftype $attr]
# Check if user has skipped an attribute which can't be skipped.
if {![string length $text2]} {return}
append text $text2
htmlGetSel
append text $htmlCurSel
set currpos [expr [getPos] + [string length $text]]
append text [htmlCloseElem $ftype]
append text "¥r"
if {$extrablankline} {append text "¥r"}
if {!$htmlIsSel && $useTabMarks} {append text "・"}
if {$htmlIsSel} { deleteSelection }
insertText $text
if {!$htmlIsSel} {
goto $currpos
}
# There is a bug in undo! Otherwise I would use the following code instead.
# if {$htmlIsSel} {
# replaceText [getPos] [selEnd] $text
# } else {
# insertText $text
# goto $currpos
# }
}
# This is used for elements that should be surrounded by empty lines
proc htmlBuildCR2Elem {ftype {attr ""}} {
global HTMLmodeVars htmlCurSel htmlIsSel
set useTabMarks $HTMLmodeVars(useTabMarks)
set text [htmlOpenCR 1]
set text2 [htmlOpenElem $ftype $attr]
# Check if user has skipped an attribute which can't be skipped.
if {![string length $text2]} {return}
append text $text2
htmlGetSel
# note elems are currently placed at left margin, ignoring current indent
append text "¥r$htmlCurSel"
set currpos [expr [getPos] + [string length $text]]
append text "¥r"
append text [htmlCloseElem $ftype]
append text "¥r¥r"
if {!$htmlIsSel && $useTabMarks} {append text "・"}
if {$htmlIsSel} { deleteSelection }
insertText $text
if {!$htmlIsSel} {
goto $currpos
}
# There is a bug in undo! Otherwise I would use the following code instead.
# if {$htmlIsSel} {
# replaceText [getPos] [selEnd] $text
# } else {
# insertText $text
# goto $currpos
# }
}
#===============================================================================
# HTML character entities
#===============================================================================
proc htmlAddCommonChars {} {
global modifiedModeVars HTMLmodeVars htmlSpecialCharacter htmlCapCharSpecMenu
global htmlSpecialSymbCharacter
set commonChars $HTMLmodeVars(commonChars)
foreach a [array names htmlSpecialCharacter] {
lappend htmlCharacters $a
}
set htmlCharacters [lsort $htmlCharacters]
foreach a [array names htmlCapCharSpecMenu] {
lappend htmlCapCharacters $a
}
set htmlCapCharacters [lsort $htmlCapCharacters]
foreach a [array names htmlSpecialSymbCharacter] {
lappend htmlSymbCharacters $a
}
set htmlSymbCharacters [lsort $htmlSymbCharacters]
set htmlAllCharacters [concat $htmlCharacters $htmlCapCharacters $htmlSymbCharacters]
if {![catch {listpick -l -p "Select chars for the commonly used char list" ¥
$htmlAllCharacters} newchars]} {
set dirty 0
foreach c $newchars {
if {[lsearch -exact $commonChars $c] < 0} {
set dirty 1
set commonChars [lsort [lappend commonChars $c]]
}
}
if {$dirty} {
lappend modifiedModeVars {commonChars HTMLmodeVars}
set HTMLmodeVars(commonChars) $commonChars
message "Rebuiding HTML menuノ"
htmlBuildMenu
message "New characters added to the common list."
}
}
}
proc htmlDefaultCommonChars {} {
global modifiedModeVars HTMLmodeVars
if {[askyesno "Revert to default common characters?"] == "yes"} {
set HTMLmodeVars(commonChars) $HTMLmodeVars(defaultCommonChars)
lappend modifiedModeVars {commonChars HTMLmodeVars}
message "Rebuiding HTML menuノ"
htmlBuildMenu
message "Common character list reverted to default."
}
}
proc htmlClearCommonChars {} {
global modifiedModeVars HTMLmodeVars
if {[askyesno "Remove all common characters?"] == "yes"} {
set HTMLmodeVars(commonChars) {}
lappend modifiedModeVars {commonChars HTMLmodeVars}
message "Rebuiding HTML menuノ"
htmlBuildMenu
message "Common character list cleared."
}
}
#
# Insert special character entity
#
proc htmlInsertCharacter {char} {
global htmlSpecialCharacter htmlCapCharSpecMenu htmlSpecialSymbCharacter
global htmlIsSel
htmlGetSel
if {$htmlIsSel} { deleteSelection }
if {[info exists htmlSpecialCharacter($char)]} {
insertText &$htmlSpecialCharacter($char)¥;
}
if {[info exists htmlCapCharSpecMenu($char)]} {
insertText &$htmlCapCharSpecMenu($char)¥;
}
if {[info exists htmlSpecialSymbCharacter($char)]} {
insertText &$htmlSpecialSymbCharacter($char)¥;
}
}
#===============================================================================
# General Commands
#===============================================================================
# remove containing tags
proc htmlUnTag {selectit} {
set curPos [getPos]
set tags [htmlGetContainer $curPos [selEnd]]
if {[llength $tags] < 5} {
alertnote "Cannot decide on enclosing tags."
return
}
# delete them
replaceText [lindex $tags 0] [lindex $tags 3] ¥
[getText [lindex $tags 1] [lindex $tags 2]]
if {$selectit} {
select [lindex $tags 0] ¥
[expr [lindex $tags 2] - [lindex $tags 1] + [lindex $tags 0]]
} else {
if {$curPos < [lindex $tags 1]} {set curPos [lindex $tags 1]}
goto [expr $curPos - [lindex $tags 1] + [lindex $tags 0]]
}
message "[lindex $tags 4] deleted."
}
# select container, like Balance (cmd-B)
proc htmlBalance {} {
# if </, stay there. If <?, back up one if possible
# watch out for end of file, beginning of file
set begin [getPos]
set end [selEnd]
set start $begin
if {$start != 0 &&
![catch {getText $start [expr $start + 2]} lookingAt] &&
$lookingAt != "</" &&
[string range $lookingAt 0 0] == "<"} {
set start [expr [getPos] - 1]
}
set tags [htmlGetContainer $start $end]
if {[llength $tags] == 5} {
select [lindex $tags 0] [lindex $tags 3]
message "[lindex $tags 4] selected."
} else {
beep
message "Cannot decide on enclosing tags."
}
}
# Select an opening tag, or remove it, of an element without a closing tag.
proc htmlSelectOpening {remove} {
set begin [getPos]
# back up one if possible and selection is wanted.
if {$begin >0 && !$remove} {incr begin -1}
set tag [htmlGetOpening $begin]
if {[llength $tag] == 3} {
if {$remove} {
deleteText [lindex $tag 0] [lindex $tag 1]
if {$begin < [lindex $tag 1]} {set begin [lindex $tag 1]}
goto [expr $begin - [lindex $tag 1] + [lindex $tag 0]]
message "[lindex $tag 2] deleted."
} else {
select [lindex $tag 0] [lindex $tag 1]
message "[lindex $tag 2] selected."
}
} else {
if {$remove} {
alertnote "Cannot find opening tag."
} else {
beep
message "Cannot find opening tag."
}
}
}
# Change an existing element.
proc htmlChangeContainer {} {
set tag [htmlGetContainer [getPos] [selEnd]]
if {[llength $tag] == 5} {
set newTag [htmlChangeElement [getText [expr [lindex $tag 0] + 1] ¥
[expr [lindex $tag 1] - 1]] [lindex $tag 4]]
if {[string length $newTag]} {
replaceText [lindex $tag 0] [lindex $tag 1] $newTag
}
} else {
alertnote "Cannot decide on enclosing tags."
}
}
proc htmlChangeOpening {} {
set tag [htmlGetOpening [getPos]]
if {[llength $tag] == 3} {
set newTag [htmlChangeElement [getText [expr [lindex $tag 0] + 1] ¥
[expr [lindex $tag 1] - 1]] [lindex $tag 2]]
if {[string length $newTag]} {
replaceText [lindex $tag 0] [lindex $tag 1] $newTag
}
} else {
alertnote "Cannot find opening tag."
}
}
#
# Exstracts all attributes to a element from a list, and puts up a dialog window
# where the user can change the attributes.
#
proc htmlChangeElement {tag elem} {
global htmlColorAttr htmlURLAttr HTMLmodeVars
global htmluserColorname htmlColorNumber htmlPackageToUse
global htmlElemAttrOptional1 htmlElemAttrOptional3
global htmlElemEventHandler1 htmlWindowAttr htmlPlugins
global htmlSpecURL htmlSpecColor htmlSpecWindow
# Remove tabs and returns from list.
regsub -all "¥[¥t¥r¥]+" $tag " " tag
# Remove element name.
set tagelem [lindex $tag 0]
set tag [string range $tag [string length $tagelem] end]
set attrs ""
set attrVals ""
# Exstract the attributes.
while {[regexp {[ ]+([^ "]+"[^"]*"|[^ "]+)} $tag thisatt]} {
set tag [string range $tag [string length $thisatt] end]
set thisatt [htmlRemoveQuotes $thisatt]
lappend attrs [string trim [lindex $thisatt 0]]
lappend attrVals [lindex $thisatt 1]
}
# All INPUT elements are defined differently. Must extract TYPE.
if {$elem == "INPUT"} {
set typeIndex [lsearch -exact [string toupper $attrs] "TYPE="]
if {$typeIndex >= 0 } {
set elem [string toupper [lindex $attrVals $typeIndex]]
# Remove TYPE attribute from list.
set attrs [lreplace $attrs $typeIndex $typeIndex]
set attrVals [lreplace $attrVals $typeIndex $typeIndex]
set used "INPUT TYPE=¥"${elem}¥""
} else {
beep
message "INPUT element without a TYPE attribute."
return
}
} else {
set used $elem
}
# If EMBED element, choose which
if {$elem == "EMBED" && $htmlPackageToUse == 1} {
if {[catch {listpick -p "Which plug-in?" [lsort $htmlPlugins]} elem] || ![string length $elem]} {return}
}
# If LI element and Extensions package, check in which list.
if {$elem == "LI"} {
set listType ""
foreach l [list UL OL DIR MENU] {
set ex "<${l}(¥[ ¥¥t¥¥r¥]+¥[^>¥]*>|>)"
set listOpening [search -s -f 0 -i 1 -r 1 -m 0 -n $ex [getPos]]
set ex2 </$l>
set listClosing [search -s -f 0 -i 1 -r 1 -m 0 -n $ex2 [getPos]]
# Search until a single list opening is found.
while {[string length $listOpening] && [string length $listClosing] &&
[lindex $listClosing 0] > [lindex $listOpening 0]} {
set listOpening [search -s -f 0 -i 1 -r 1 -m 0 -n $ex [expr [lindex $listOpening 0] - 1]]
set listClosing [search -s -f 0 -i 1 -r 1 -m 0 -n $ex2 [expr [lindex $listClosing 0] - 1]]
}
if {[string length $listOpening]} {
lappend listType "$listOpening $l"
}
}
set ltype [lindex [lindex $listType 0] 2]
set lnum [lindex [lindex $listType 0] 0]
for {set i 1} {$i < [llength $listType]} {incr i} {
if {[lindex [lindex $listType $i] 0] > $lnum} {
set ltype [lindex [lindex $listType $i] 2]
set lnum [lindex [lindex $listType $i] 0]
}
}
if {$ltype == "UL"} {
set elem "LI IN UL"
} elseif {$ltype == "OL"} {
set elem "LI IN OL"
}
}
set eventText ""
# JavaScript event handlers. Extension package only.
if {$htmlPackageToUse == 1 && [info exists htmlElemEventHandler1($elem)]} {
set eventHandler [string toupper $htmlElemEventHandler1($elem)]
} else {
set eventHandler ""
}
# Remove event handler from attributes list,
# if they should not be included, and save them to put them back later.
set attrsToupper [string toupper $attrs]
if {!$HTMLmodeVars(inclEventHandler)} {
foreach ev $eventHandler {
set evIndex [lsearch -exact $attrsToupper $ev]
if {$evIndex >=0} {
append eventText " " [lindex $attrs $evIndex] ¥
[htmlAddQuotes [lindex $attrVals $evIndex]]
set attrs [lreplace $attrs $evIndex $evIndex]
set attrVals [lreplace $attrVals $evIndex $evIndex]
set attrsToupper [lreplace $attrsToupper $evIndex $evIndex]
}
}
}
set attrs $attrsToupper
# Element known by HTML mode?
if {![info exists htmlElemAttrOptional${htmlPackageToUse}($elem)]} {
alertnote "Unknown element: $elem"
return
}
set allAttrs [concat [htmlGetRequired $elem] [htmlGetOptional $elem]]
if {[string length $eventHandler]} {append allAttrs " " $eventHandler}
set choices [htmlGetChoices $elem]
set numAttrs [htmlGetNumber $elem]
set errText ""
# Check if there are some unknown attributes.
foreach a $attrs {
if {[lsearch -exact $allAttrs $a] < 0} {
lappend errText "Unknown attribute: $a"
}
}
# Does this element have any attributes?
if {![llength $allAttrs]} {
if {[llength $errText]} {
if {[askyesno "$elem has no attributes. Remove the ones in the text?"] == "no"} {
return
} else {
# Remove the error text to prevent another popup window.
set errText ""
}
} else {
message "$elem has no attributes."
return
}
}
# Add two dummy elements for OK and Cancel buttons.
set values {0 0}
# Build a list with attribute vales.
foreach a $allAttrs {
set attrIndex [lsearch -exact $attrs $a]
if {$attrIndex >= 0 } {set aval [lindex $attrVals $attrIndex]}
set a2 [string trimright $a =]
if {([lsearch -exact $htmlURLAttr $a] >= 0 && [lsearch -exact $htmlSpecURL "${elem}!=$a2"] < 0) || ¥
[lsearch -exact $htmlSpecURL "${elem}=$a2"] >= 0} {
# URL
if {$attrIndex >= 0} {
htmlAddToCache URLs $aval
lappend values "" $aval 0
} else {
lappend values "" "No value" 0
}
} elseif {([lsearch -exact $htmlColorAttr $a] >= 0 && [lsearch -exact $htmlSpecColor "${elem}!=$a2"] < 0) || ¥
[lsearch -exact $htmlSpecColor "${elem}=$a2"] >= 0} {
# Color
if {$attrIndex >= 0} {
set aval [htmlCheckColorNumber $aval]
if {$aval == 0} {
lappend errText "$a: Invalid color number."
lappend values "" "No value" 0
}
if {[info exists htmluserColorname($aval)]} {
lappend values "" $htmluserColorname($aval) 0
} elseif {[info exists htmlColorNumber($aval)]} {
lappend values "" $htmlColorNumber($aval) 0
} else {
lappend values $aval "No value" 0
}
} else {
lappend values "" "No value" 0
}
} elseif {([lsearch -exact $htmlWindowAttr $a] >= 0 && [lsearch -exact $htmlSpecWindow "${elem}!=$a2"] < 0) || ¥
[lsearch -exact $htmlSpecWindow "${elem}=$a2"] >= 0} {
# Window
if {$attrIndex >= 0} {
if {[lsearch -exact [list _SELF _TOP _PARENT _BLANK] [string toupper $aval]] < 0} {
htmlAddToCache windows $aval
} else {
set aval [string toupper $aval]
}
lappend values "" $aval
} else {
lappend values "" "No value"
}
} elseif {[lsearch $numAttrs "${a}*"] >= 0} {
# Number
if {$attrIndex >= 0} {
set numcheck [htmlCheckAttrNumber $elem $a $aval]
if {$numcheck == 1} {
lappend values $aval
} else {
lappend errText "$a: $numcheck"
lappend values ""
}
} else {
lappend values ""
}
} elseif {[string match "*${a}*" $choices] && [string index $a [expr [string length $a] - 1]] == "="} {
# Choices
if {$attrIndex >= 0} {
set match ""
if {!(($elem == "OL" || $elem == "LI IN OL") && $a == "TYPE=")} {
set aval [string toupper $aval]
}
foreach w $choices {
if {$w == "${a}${aval}"} {
set match $aval
}
}
if {[string length $match]} {
lappend values $match
} else {
lappend errText "$a: Unknown choice, $aval."
lappend values "No value"
}
} else {
lappend values "No value"
}
} elseif {[string index $a [expr [string length $a] - 1]] == "="} {
# Any other
if {$attrIndex >= 0} {
lappend values $aval
} else {
lappend values ""
}
} elseif {$attrIndex >= 0} {
# Flag
lappend values 1
} else {
lappend values 0
}
}
# If invalid attributes, continue?
if {[llength $errText] && ![htmlErrorWindow "$elem not well-defined" $errText 1]} {
return
}
set r [htmlOpenElemWindow $used $elem $values]
# Put back event handlers. Empty string means "Cancel", do nothing.
if {[string length $r]} {
set r "[string range $r 0 [expr [string length $r] - 2]]$eventText>"
}
return $r
}
# Splits an attribute into its name and value and remove quotes.
proc htmlRemoveQuotes {attrStr} {
# Is it a flag?
if {![string match "*=*" $attrStr]} {return [string toupper $attrStr]}
set attr [string range $attrStr 0 [string first "=" $attrStr]]
# Get the attribute value.
set attrVal [string range $attrStr [expr [string first "=" $attrStr] + 1] end]
return [list $attr [string trim $attrVal ¥"]]
}
#
# launch a viewer and pass this window to it
#
proc htmlSendWindow {{path ""}} {
global HTMLmodeVars browserSig
if {[catch {launchBackApplSigs {MOSS } browserSig}]} {
getApplSig "Please locate your web browser" browserSig
}
set name [file tail [launchBackAppl $browserSig]]
if {$path == ""} {
set path [stripNameCount [car [winNames -f]]]
if {[winDirty]} {
case [askyesno -c "Save '[file tail $path]'?"] in {
"yes" {save}
"no" {}
"cancel" {return}
}
}
}
sendOpenEvent -n $name $path
if {$HTMLmodeVars(browseInForeground)} { switchTo $name }
}
proc htmlCleanUpCache {cache} {
global HTMLmodeVars
global modifiedModeVars
set URLs $HTMLmodeVars($cache)
if {![llength $URLs]} {
alertnote "No $cache are cached."
return 1
}
set urlnumber [llength $URLs]
set screenHeight [lindex [getMainDevice] 3]
set maxLines [expr ($screenHeight - 160) / 20]
set pages [expr ($urlnumber - 1) / $maxLines ]
set thispage 0
set finished 0
set canceled 0
set checked 1
while {!$finished} {
if {$thispage < $pages} {
set thisurlnumber $maxLines
} else {
set thisurlnumber [expr ($urlnumber - 1 ) % $maxLines + 1]
}
set height [expr 75 + $thisurlnumber * 20]
set box "-w 440 -h $height -b OK 20 [expr $height - 30] 85 [expr $height - 10] ¥
-b Cancel 110 [expr $height - 30] 175 [expr $height - 10] ¥
-b {Uncheck all} 200 [expr $height - 30] 285 [expr $height - 10] ¥
-t {Uncheck the $cache you want to remove} 10 10 440 30 "
set hpos 30
set thisURLs [lrange $URLs [expr $thispage * $maxLines] ¥
[expr $thispage * $maxLines + $maxLines - 1]]
foreach url $thisURLs {
lappend box -c $url $checked 10 $hpos 390 [expr $hpos + 15]
incr hpos 20
}
if {$thispage < $pages} {
lappend box -b "Moreノ" 310 [expr $height - 30] 375 [expr $height - 10]
}
set thisbox [eval [concat dialog $box]]
if {[lindex $thisbox 1]} { # cancel
set finished 1
set canceled 1
} elseif {[lindex $thisbox 2]} {
set checked 0
} else {
if {$thispage == $pages} {
set ll 1
} else {
set ll 2
}
append URLsToSave " " [lrange $thisbox 3 [expr [llength $thisbox] - $ll]]
if {[lindex $thisbox 0]} { # OK
set finished 1
} else { # more
set thispage [expr $thispage + 1]
set checked 1
}
}
}
set newurls ""
if {!$canceled} {
set saveurlnumber [llength $URLsToSave]
for {set i 0} {$i < $saveurlnumber} {incr i} {
if {[lindex $URLsToSave $i]} {
lappend newurls [lindex $URLs $i]
}
}
if {$saveurlnumber < $urlnumber} {
append newurls " " [lrange $URLs $saveurlnumber end]
}
set URLs $newurls
set HTMLmodeVars($cache) $URLs
lappend modifiedModeVars [list $cache HTMLmodeVars]
}
}
proc htmlSelToURL {} {
set newurl [string trim [getSelect]]
# Don't add if there are spaces, tabs or returns.
if {[regexp {[ ¥t¥r]+} $newurl]} {
alertnote "Selection contains spaces. It will not be added to URL cache."
return
}
if {[string length $newurl]} {
htmlAddToCache URLs $newurl
message "$newurl added to URLs."
} else {
beep
message "No selection!"
}
}
proc htmlScrapToURL {} {
set newurl [string trim [getScrap]]
# Don't add if there are spaces, tabs or returns.
if {[regexp {[ ¥t¥r]+} $newurl]} {
alertnote "Clipboard contains spaces. It will not be added to URL cache."
return
}
if {[string length $newurl]} {
htmlAddToCache URLs $newurl
message "$newurl added to URLs."
} else {
beep
message "Clipboard empty!"
}
}
proc htmlClearCache {cache} {
global HTMLmodeVars modifiedModeVars
if {[askyesno "Remove all $cache from [string range $cache 0 [expr [string length $cache] - 2]] cache?"] == "yes"} {
set HTMLmodeVars($cache) {}
lappend modifiedModeVars [list $cache HTMLmodeVars]
}
}
#==============================================================================
#
# Colors
#
#==============================================================================
# Convert colour names to numbers and vice versa.
# Colour name or number must be quoted for this to work.
proc htmlRevealColor {} {
global htmlColorName htmlColorNumber htmlColorAttr htmluserColors
global htmluserColorname
set searchstring "("
foreach s $htmlColorAttr {
append searchstring "${s}|"
}
# remove last |
set searchstring [string trimright $searchstring |]
append searchstring ")((¥[^ ¥¥t¥¥r¥">¥]+)|¥"(¥[^¥"¥]+)¥")"
set startpos [getPos]
set endpos [selEnd]
set cantfind 0
# find attribute
set f [search -s -f 0 -r 1 -i 1 -n -m 0 $searchstring $startpos]
if {![string length $f] || [lindex $f 1] < $endpos} {
set cantfind 1
}
if {!$cantfind} {
set txt [getText [lindex $f 0] [lindex $f 1]]
regexp -indices -nocase $searchstring $txt a b c
set cpos [expr [lindex $f 0] + [lindex $c 0]]
set epos [expr [lindex $f 0] + [lindex $c 1] + 1]
set col [string trim [string range $txt [lindex $c 0] [lindex $c 1]] ¥"]
if {[info exists htmlColorName($col)]} {
replaceText $cpos $epos "¥"$htmlColorName($col)¥""
} elseif {[info exists htmlColorNumber($col)]} {
replaceText $cpos $epos "¥"$htmlColorNumber($col)¥""
} elseif {[info exists htmluserColorname($col)]} {
replaceText $cpos $epos "¥"$htmluserColorname($col)¥""
} elseif {[info exists htmluserColors($col)]} {
replaceText $cpos $epos "¥"$htmluserColors($col)¥""
} else {
beep
message "Don't recognize color."
}
} else {
beep
message "Current position is not at a color attribute."
}
}
# Prompt a for a new color. Returns the color name. If cancel, returns ""
proc htmlAddNewColor {} {
global htmluserColors htmluserColorname basicColors htmlColorNumber
set alluserColors [array names htmluserColors]
set hexa {A B C D E F}
set newcolor [colorTriple "New color"]
if {![string length $newcolor]} {return }
set red [expr [lindex $newcolor 0] / 256]
set green [expr [lindex $newcolor 1] / 256]
set blue [expr [lindex $newcolor 2] / 256]
set red1 [expr $red / 16]
set red2 [expr $red % 16]
set green1 [expr $green / 16]
set green2 [expr $green % 16]
set blue1 [expr $blue / 16]
set blue2 [expr $blue % 16]
set colornumber {#}
foreach c [list $red1 $red2 $green1 $green2 $blue1 $blue2] {
if {$c > 9} {
set c1 [lindex $hexa [expr $c - 10]]
} else {
set c1 $c
}
append colornumber $c1
}
# See if the colour already exists.
if {![catch {set colTest $htmlColorNumber($colornumber)}] || ¥
![catch {set colTest $htmluserColorname($colornumber)}]} {
alertnote "This color is identical with '$colTest'. Two identical ¥
colors cannot be defined."
return
}
set noname 1
while {$noname} {
if {[catch {prompt "Color name" ""} colorname]} { # cancel
set noname 0
return
} else {
set colorname [string trim $colorname]
if {[lsearch -exact $basicColors $colorname] >= 0} {
alertnote "Predefined color. Choose another name."
} elseif {[string length $colorname]} {
set replace 0
if {[lsearch -exact $alluserColors $colorname] >= 0 } {
set repl [dialog -w 200 -h 75 -b Cancel 20 40 80 60 ¥
-b Replace 115 40 175 60 ¥
-t "Replace $colorname?" 10 10 150 30]
if {[lindex $repl 1] } {
set replace 1
# remove the color first
set oldnumber $htmluserColors($colorname)
htmlColordelete $colorname $oldnumber
}
} else {
set replace 1
}
if {$replace} { # add the new color
set noname 0
htmlColordef $colorname $colornumber
message "Color saved!"
}
} else {
alertnote "You must name the color."
}
}
}
return $colorname
}
proc htmlChangeColor {} {
global htmluserColors htmluserColorname basicColors htmlColorNumber
set hexa {A B C D E F}
set colors [lsort [array names htmluserColors]]
if {![string length $colors]} {
alertnote "No colors are defined."
return
}
if {[catch {listpick -p "Select the color to change" $colors} changeColor] || ¥
![string length $changeColor]} {return}
# Calculate the red green and blue numbers.
set colornumber $htmluserColors($changeColor)
set red1 [string range $colornumber 1 1]
set red2 [string range $colornumber 2 2]
set green1 [string range $colornumber 3 3]
set green2 [string range $colornumber 4 4]
set blue1 [string range $colornumber 5 5]
set blue2 [string range $colornumber 6 6]
foreach c [list $red1 $red2 $green1 $green2 $blue1 $blue2] {
switch $c {
A {set c1 10}
B {set c1 11}
C {set c1 12}
D {set c1 13}
E {set c1 14}
F {set c1 15}
default {set c1 $c}
}
lappend numbers $c1
}
set red [expr [lindex $numbers 0] * 4096 + [lindex $numbers 1] * 256]
set green [expr [lindex $numbers 2] * 4096 + [lindex $numbers 3] * 256]
set blue [expr [lindex $numbers 4] * 4096 + [lindex $numbers 5] * 256]
# Get a new colour.
set newcolor [colorTriple $changeColor $red $green $blue]
if {![string length newcolor]} {return}
set red [expr [lindex $newcolor 0] / 256]
set green [expr [lindex $newcolor 1] / 256]
set blue [expr [lindex $newcolor 2] / 256]
set red1 [expr $red / 16]
set red2 [expr $red % 16]
set green1 [expr $green / 16]
set green2 [expr $green % 16]
set blue1 [expr $blue / 16]
set blue2 [expr $blue % 16]
set newnumber {#}
foreach c [list $red1 $red2 $green1 $green2 $blue1 $blue2] {
if {$c > 9} {
set c1 [lindex $hexa [expr $c - 10]]
} else {
set c1 $c
}
append newnumber $c1
}
# See if the colour already exists.
if {( ![catch {set colTest $htmlColorNumber($newnumber)}] || ¥
![catch {set colTest $htmluserColorname($newnumber)}] ) && ¥
$colTest != $changeColor} {
alertnote "This color is identical with '$colTest'. Two identical ¥
colors cannot be defined."
return
}
set noname 1
# Choose a new name for the colour.
while {$noname} {
if {[catch {prompt "Color name" $changeColor} colorname]} {
set noname 0
} else {
set colorname [string trim $colorname]
if {[lsearch -exact $basicColors $colorname] >= 0} {
alertnote "Predefined color. Choose another name."
} elseif {[string length $colorname]} {
set replace 0
if {[lsearch -exact $colors $colorname] >= 0 &&
$colorname != $changeColor} {
set repl [dialog -w 200 -h 75 -b Cancel 20 40 80 60 ¥
-b Replace 115 40 175 60 ¥
-t "Replace $colorname?" 10 10 150 30]
if {[lindex $repl 1] } {
set replace 1
# remove the color first
set oldnumber $htmluserColors($colorname)
htmlColordelete $colorname $oldnumber
}
} else {
set replace 1
}
if {$replace} {
# remove the old colour
htmlColordelete $changeColor $colornumber
set noname 0
# add the new colour
htmlColordef $colorname $newnumber
message "Color changed."
}
} else {
alertnote "You must name the color."
}
}
}
}
proc htmlRemoveColors {} {
global htmluserColors htmluserColorname
set colors [lsort [array names htmluserColors]]
if {![string length $colors]} {
alertnote "No colors are defined."
return
}
if {![catch {listpick -l -p "Select the colors to remove" $colors} removeColors] && ¥
[string length $removeColors]} {
foreach c $removeColors {
set colornumber $htmluserColors($c)
htmlColordelete $c $colornumber
}
message "Colors removed."
}
}
proc htmlColordef {colorname colornumber} {
global htmluserColors htmluserColorname
set htmluserColors($colorname) $colornumber
set htmluserColorname($colornumber) $colorname
addArrDef htmluserColors $colorname $colornumber
addArrDef htmluserColorname $colornumber $colorname
}
proc htmlColordelete {colorname colornumber} {
global htmluserColors htmluserColorname
catch {unset htmluserColors($colorname)}
catch {unset htmluserColorname($colornumber)}
removeArrDef htmluserColors $colorname
removeArrDef htmluserColorname $colornumber
}
# Set the home page URL
proc htmlServerURL {} {
global modifiedModeVars HTMLmodeVars
set baseURL $HTMLmodeVars(baseURL)
set basePath $HTMLmodeVars(basePath)
set val [dialog -w 450 -h 110 -t "Server URL:" 10 10 90 30 ¥
-e $baseURL 100 10 440 25 -t "Path:" 50 45 90 55 ¥
-e $basePath 100 45 440 60 -b OK 20 80 85 100 -b Cancel 110 80 175 100]
if {[lindex $val 2]} {
# Add / at the end if necessary.
set baseURL [string trim [lindex $val 0]]
set basePath [string trim [lindex $val 1]]
if {[string length $baseURL] && ¥
[string range $baseURL [expr [string length $baseURL] - 1] end] != "/"} {
append baseURL "/"
}
if {[string length $basePath]} {
if {[string range $basePath [expr [string length $basePath] - 1] end] != "/"} {
append basePath "/"
}
# Remove / from beginning of path.
set basePath [string trimleft $basePath /]
}
set HTMLmodeVars(basePath) $basePath
set HTMLmodeVars(baseURL) $baseURL
lappend modifiedModeVars {baseURL HTMLmodeVars} {basePath HTMLmodeVars}
}
}
# Define a file as a footer.
proc htmlFooter {} {
global HTMLmodeVars modifiedModeVars
set footers $HTMLmodeVars(footers)
if {![catch {getfile "Select the file with the footer."} newFooter]} {
getFileInfo $newFooter filetest
if {$filetest(type) != "TEXT"} {
alertnote "'[file tail $newFooter]' is not a text file."
return
} elseif {[lsearch -exact $footers $newFooter] < 0} {
# Can't define two footers with the same file name.
foreach f $footers {
if {[file tail $f] == [file tail $newFooter]} {
alertnote "There is already a footer with the filename¥
'[file tail $newFooter]'. Two footers with the same filename¥
cannot be defined."
return
}
}
lappend footers $newFooter
set HTMLmodeVars(footers) $footers
lappend modifiedModeVars {footers HTMLmodeVars}
} else {
alertnote "$newFooter already a footer."
return
}
message "[file tail $newFooter] is now a footer."
}
}
# Remove footers from list.
proc htmlRemoveFooter {} {
global HTMLmodeVars modifiedModeVars
set footers $HTMLmodeVars(footers)
if {![llength $footers]} {
alertnote "No footers are defined."
return
}
foreach f $footers {
lappend foot [file tail $f]
}
if {![catch {listpick -l -p "Select the footers to remove" $foot} newFooters] && ¥
[string length $newFooters]} {
set newFoot ""
foreach f $foot {
if {[lsearch -exact $newFooters $f] < 0} {
lappend newFoot [lindex $footers [lsearch -exact $foot $f]]
}
}
set HTMLmodeVars(footers) $newFoot
lappend modifiedModeVars {footers HTMLmodeVars}
message "Footers removed."
}
}
# Insert a footer in the document
proc htmlInsertFooter {} {
global HTMLmodeVars
set footers $HTMLmodeVars(footers)
if {![llength $footers]} {
alertnote "No footers are defined."
return
}
foreach f $footers {
lappend foot [file tail $f]
}
if {![catch {listpick -p "Select the footer to insert" $foot} footval] && ¥
[string length $footval]} {
set footerFile [lindex $footers [lsearch -exact $foot $footval]]
if {![catch {readFile $footerFile} footText]} {
insertText "¥r$footText¥r"
} else {
alertnote "Could not read $footerFile"
return
}
message "[file tail $footerFile] inserted."
}
}